{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "class Perceptron(object):\n",
    "    \"\"\"Perceptron classifier.\n",
    "\n",
    "    Parameters\n",
    "    ------------\n",
    "    eta:float\n",
    "        Learning rate (between 0.0 and 1.0)\n",
    "    n_iter:int\n",
    "        Passes over the training dataset.\n",
    "\n",
    "    Attributes\n",
    "    -------------\n",
    "    w_: 1d-array\n",
    "        Weights after fitting.\n",
    "    errors_: list\n",
    "        Numebr of misclassifications in every epoch.\n",
    "\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, eta=0.01, n_iter=10):\n",
    "        self.eta = eta\n",
    "        self.n_iter = n_iter\n",
    "\n",
    "    def fit(self, X, y):\n",
    "        \"\"\"Fit training data.\n",
    "\n",
    "        Parameters\n",
    "        ------------\n",
    "        X: {array-like}, shape=[n_samples, n_features]\n",
    "            Training vectors, where n_samples is the number of samples\n",
    "            and n_featuers is the number of features.\n",
    "        y: array-like, shape=[n_smaples]\n",
    "            Target values.\n",
    "\n",
    "        Returns\n",
    "        ----------\n",
    "        self: object\n",
    "        \"\"\"\n",
    "\n",
    "        self.w_ = np.zeros(1 + X.shape[1]) # Add w_0\n",
    "        self.errors_ = []\n",
    "\n",
    "        for _ in range(self.n_iter):\n",
    "            errors = 0\n",
    "            for xi, target in zip(X, y):\n",
    "                update = self.eta * (target - self.predict(xi))\n",
    "                self.w_[1:] += update * xi\n",
    "                self.w_[0] += update\n",
    "                errors += int(update != 0.0)\n",
    "            self.errors_.append(errors)\n",
    "        return self\n",
    "\n",
    "    def net_input(self, X):\n",
    "        \"\"\"Calculate net input\"\"\"\n",
    "        return np.dot(X, self.w_[1:]) + self.w_[0]\n",
    "\n",
    "    def predict(self, X):\n",
    "        \"\"\"Return class label after unit step\"\"\"\n",
    "        return np.where(self.net_input(X) >= 0.0, 1, -1) #analoge ? : in C++"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#coding:utf-8\n",
    "#**********************************https://ljalphabeta.gitbooks.io/python-/content/ch2section3.html\n",
    "#pərˈsepträn\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from matplotlib.colors import ListedColormap\n",
    "import Perceptron as perceptron_class\n",
    "\n",
    "df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)\n",
    "#print df.tail()\n",
    "\n",
    "#抽取出前100条样本，这正好是Setosa和Versicolor对应的样本，我们将Versicolor对应的数据作为类别1，Setosa对应的作为-1。\n",
    "# 对于特征，我们抽取出sepal length和petal length两维度特征，然后用散点图对数据进行可视化\n",
    "\n",
    "y = df.iloc[0:100, 4].values\n",
    "y = np.where(y == 'Iris-setosa', -1, 1)\n",
    "X = df.iloc[0:100, [0, 2]].values\n",
    "# plt.scatter(X[:50, 0], X[:50, 1],color='red', marker='o', label='setosa')\n",
    "# plt.scatter(X[50:100, 0], X[50:100, 1],color='blue', marker='x', label='versicolor')\n",
    "# plt.xlabel('sepal length')\n",
    "# plt.ylabel('petal length')\n",
    "# plt.legend(loc='upper left')\n",
    "# plt.show()\n",
    "\n",
    "#这里是对于感知机模型进行训练\n",
    "ppn = perceptron_class.Perceptron(eta=0.1, n_iter=10)\n",
    "ppn.fit(X, y)\n",
    "\n",
    "#画出分界线\n",
    "def plot_decision_regions(X, y, classifier, resolution=0.02):\n",
    "    # setup marker generator and color map\n",
    "    markers = ('s', 'x', 'o', '^', 'v')\n",
    "    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')\n",
    "    cmap = ListedColormap(colors[:len(np.unique(y))])\n",
    "    # plot the decision surface\n",
    "    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1\n",
    "    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1\n",
    "    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution))\n",
    "    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)\n",
    "    Z = Z.reshape(xx1.shape)\n",
    "    print(xx1)\n",
    "    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)\n",
    "    plt.xlim(xx1.min(), xx1.max())\n",
    "    plt.ylim(xx2.min(), xx2.max())\n",
    "    # plot class samples\n",
    "    for idx, cl in enumerate(np.unique(y)):\n",
    "        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],\n",
    "                    alpha=0.8, c=cmap(idx),\n",
    "                    marker=markers[idx], label=cl)\n",
    "\n",
    "plot_decision_regions(X, y, classifier=ppn)\n",
    "plt.xlabel('sepal length [cm]')\n",
    "plt.ylabel('petal length [cm]')\n",
    "plt.legend(loc='upper left')\n",
    "plt.show()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
